/*
 *  url (del server) al que se hace el request 
 */
Client.url = "http://127.0.0.1:3000/server";

/**
 * Constructor. Se le pasa el callback y la data del request.
 */
function Client(callback, request) {
    var data = request.serialize();
    this.callback = callback;
    this.socket = new XMLHttpRequest();
    this.socket.open("POST", Client.url, true);
    this.socket.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    this.socket.setRequestHeader("Connection", "keep-alive");
    this.socket.setRequestHeader("Content-length", data.length);
    this.socket.onreadystatechange = this.processState;
    this.socket.client = this;
    this.timeout = new Timeout(this.timeoutCallback, 2000, this);
    try {
        this.socket.send(data);
    } catch(ex) {
        console.log("Excepcion en el send()");
        this.callback(this.getError());
    }
};

/**
 * callback del XMLHttpRequest
 */
Client.prototype.processState = function () {
    if(this.readyState == 4 && this.status == 200) {
        window.clearTimeout(this.client.timeoutID);
        this.client.timeout.kill();
        client.callback(client.getError());
    }
};

/**
 * callback del timeout.
 */
Client.prototype.timeoutCallback = function(client) {
    client.socket.abort();
    client.callback(client.getError());
}

/**
 * devuelve el status del request una vez concluido
 */
Client.prototype.getError = function () {
    return this.socket.status == 200 ? 0:1;
};

/**
 * devuelve la respuesta del request una vez concluido
 */
Client.prototype.getResponse = function () {
    if (this.isReady() && this.getError() == 0) {
        return new Response(this.socket.responseText);
    } else {
        throw "Not Ready";        
    }
};

/**
 * aborta el request actual
 */
Client.prototype.abort = function() {
    this.socket.abort();
    this.timeout.kill();
};

/**
 * indica si el request ya terminó de trabajar por la razón que fuera
 */
Client.prototype.isReady = function() {
    return (this.socket.readyState == 4 || this.socket.readyState == 0) ? true : false;
}